package com.gitee.chenyaohua.oa.action;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONPath;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.gitee.chenyaohua.oa.config.Const;
import com.gitee.chenyaohua.oa.dao.UserRepository;
import com.gitee.chenyaohua.oa.domain.TRight;
import com.gitee.chenyaohua.oa.domain.TUser;
import com.gitee.chenyaohua.oa.from.dto.Status;
import com.gitee.chenyaohua.oa.from.dto.ToEmail;
import com.gitee.chenyaohua.oa.from.validator.*;
import com.gitee.chenyaohua.oa.from.vo.*;
import com.gitee.chenyaohua.oa.service.EmailService;
import com.gitee.chenyaohua.oa.service.UserService;
import com.gitee.chenyaohua.oa.service.VerificationCodeService;
import com.gitee.chenyaohua.oa.util.io.IOUtil;
import com.gitee.chenyaohua.oa.util.jwt.JwtTokenUtil;
import lombok.extern.slf4j.Slf4j;
import org.activiti.engine.*;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.io.ClassPathResource;
import org.springframework.security.crypto.factory.PasswordEncoderFactories;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;

import java.io.IOException;
import java.io.InputStream;
import java.text.MessageFormat;
import java.util.Date;
import java.util.List;
import java.util.stream.Collectors;

@Slf4j
@RestController
@RequestMapping("/user")
public class UserController {
 
	@Autowired
	private RuntimeService runtimeService;
	
	@Autowired
	private RepositoryService repositoryService;
	
	@Autowired
	private TaskService taskService;
	
	@Autowired
	private FormService formService;

	@Autowired
	private IdentityService identityService;
	
    @Autowired
    private UserRepository userRepository;

    @Autowired
    private ObjectMapper objectMapper;

    @Autowired
    private UserService userService;


	@Autowired
	private VerificationCodeService verificationCodeService;
 
    @PostMapping("/registration")
    public Result<String> registration(@Validated(value = {UserRegistrationCheck.class}) @RequestBody UserRegistrationFrom userFrom){
    	//注册
    	log.debug("注册用户{}",JSON.toJSONString(userFrom,Const.BEAN_VALUE_FILTER));
		Result.ResultBuilder<String> builder = Result.builder();
		String verificationCode = verificationCodeService.getVerificationCode(userFrom.getUserEmail());
		if(!userFrom.getCode().equals(verificationCode)){
			return builder.msg("验证码验证失败").status(Status.FAIL.getIndex()).build();
		}

		if(!StringUtils.equals(userFrom.getNewPasswrod(), userFrom.getUserPasswrod())) {
    		return builder.msg("前后密码不相同。").status(Status.FAIL.getIndex()).build();
    	}
    	
    	TUser tuser = new TUser();
    	BeanUtils.copyProperties(userFrom, tuser);
    	
    	String encode = PasswordEncoderFactories.createDelegatingPasswordEncoder().encode(tuser.getUserPasswrod());
    	tuser.setUserPasswrod(encode);
    	tuser.setCreateDate(new Date());
    	tuser.setUpdateDate(new Date());
    	userRepository.save(tuser);
    	
       return  builder.msg("注册成功").status(Status.SUCCESS.getIndex()).build();
    }
    
    @PostMapping("/login")
    public Result<String> login(@Validated(UserLoginCheck.class) @RequestBody UserLoginFrom loginForm) throws Exception{
    	log.debug("登录参数日志：{}", JSON.toJSONString(loginForm, Const.BEAN_VALUE_FILTER));
    	TUser tuser = userRepository.findByUserEmail(loginForm.getUserEmail());
		Result.ResultBuilder<String> builder = Result.builder();

		if(tuser!=null) {
        	boolean encode = PasswordEncoderFactories.createDelegatingPasswordEncoder().matches(loginForm.getUserPasswrod(),tuser.getUserPasswrod());
    		if(encode) {
    			ClassPathResource idrsa = new ClassPathResource("secret/rsa/id_rsa");
    			InputStream inputStream = idrsa.getInputStream();
    			String readFull = IOUtil.readFull(inputStream);
    			String token = JwtTokenUtil.generateToken(tuser.getUserEmail(),readFull);
				return builder.data(token).status(Status.SUCCESS.getIndex()).build();
			}
			return builder.msg("账户或密码不正确。").status(Status.FAIL.getIndex()).build();
		}
		return builder.msg("不存在该用户。").status(Status.FAIL.getIndex()).build();
	}
    
    /**
     * 删除用户
     * @param id	用户id
     * @return	
     */
    @DeleteMapping("{id}")
    public Result<String> drop(@PathVariable("id")String id){
    	userRepository.deleteById(id);
       return  new Result<>(Status.SUCCESS.getIndex(), null,"删除成功");
    }
    
    /**
     * 修改用户
     * @param user	用户实例
     * @return	
     */
    @PutMapping("/{id}")
    public Result<String> update(@Validated(value = UserModifieCheck.class) @RequestBody TUser user){
		userService.update(user);
		return   new Result<>(Status.SUCCESS.getIndex(), null,"修改成功");
    }


	/**
	 * 修改用户
	 * @param user	用户实例
	 * @return
	 */
	@PostMapping("/password")
	public Result<String> resetPassword(@RequestHeader(value = "Authorization") String token,
										@Validated(value = ResetPasswordCheck.class) @RequestBody UserRegistrationFrom user) throws IOException {
		if(!StringUtils.equals(user.getNewPasswrod(),user.getUserPasswrod())){
			return new Result<>(Status.FAIL.getIndex(), null,"前后密码不一致");
		}

		if(token==null){
			return new Result<>(Status.FAIL.getIndex(), null,"token值不能存在");
		}

		String payload = JwtTokenUtil.decodeToken(token);
		String email = (String) JSONPath.read(payload, "sub");
		TUser byUserEmail = userRepository.findByUserEmail(email);

		byUserEmail.setUserPasswrod(PasswordEncoderFactories.createDelegatingPasswordEncoder().encode(user.getNewPasswrod()));
		byUserEmail.setUpdateDate(new Date());
		userService.update(byUserEmail);
		return   new Result<>(Status.SUCCESS.getIndex(), null,"修改成功");
	}

	/**
	 * 修改用户
	 * @param token	token值
	 * @return
	 */
	@GetMapping("/info")
	public Result<UserInfoVo> getUser(@RequestHeader(value = "Authorization") String token) throws IOException{
		log.debug("token值：[{}]",token);
		String payload = JwtTokenUtil.decodeToken(token);
		UserInfoVo userInfoVo = new UserInfoVo();
		String email = (String) JSONPath.read(payload, "sub");
		TUser user = userRepository.findByUserEmail(email);
		List<TRight> rights = user.getRoles().stream().flatMap(x -> x.getRights().stream()).collect(Collectors.toList());
		log.debug(user.toString());
		BeanUtils.copyProperties(user,userInfoVo);
		userInfoVo.setItems(rights);
		return new Result<>(Status.SUCCESS.getIndex(),userInfoVo,null) ;
	}

	/**
	 * 获取验证码
	 * @param verification	邮箱信息
	 * @return
	 */
	@GetMapping("/verificationCode")
	public Result<String> verificationCode(@Validated(value = {GetVerificationCode.class})  VerificationFrom verification) {
		Result<String> result = null;
		switch (verification.getType()){
			case REGIST:
				userService.getVerificationCode(verification.getEmail());
				result = new Result<>(Status.SUCCESS.getIndex(), null,"发送成功");
				break;
			case RESET_PASSWORD:
				TUser user = userRepository.findByUserEmail(verification.getEmail());
				if(user!=null){
					userService.getVerificationCode(verification.getEmail());
					result = new Result<>(Status.SUCCESS.getIndex(), null,"发送成功");
				}else{
					result = new Result<>(Status.FAIL.getIndex(), null,"邮箱不存在发送失败");
				}
				break;
			default:
				log.error("该类型未做处理["+verification.getType()+"]");
				throw new RuntimeException("");
		}
		return result;
	}



	/**
	 * 校验验证码
	 * @param from	验证信息
	 * @return
	 */
	@PostMapping("/checkVerificationCode")
	public Result<String> checkVerificationCode(@Validated(value = {CheckVerificationCode.class}) @RequestBody VerificationFrom from) throws Exception  {
		TUser user = userRepository.findByUserEmail(from.getEmail());
		Result.ResultBuilder<String> builder = Result.builder();
		if(user!=null){
			String code = verificationCodeService.getVerificationCode(from.getEmail());
			if(StringUtils.isEmpty(code)){

				return builder.msg("验证码已失效").status(Status.FAIL.getIndex()).build();
			}
			if(StringUtils.equals(code,from.getCode())){
				ClassPathResource idrsa = new ClassPathResource("secret/rsa/id_rsa");
				InputStream inputStream = idrsa.getInputStream();
				String readFull = IOUtil.readFull(inputStream);
				return builder.msg("验证成功").data(JwtTokenUtil.generateToken(from.getEmail(),readFull)).status(Status.SUCCESS.getIndex()).build();
			}
			return builder.msg("验证失败").status(Status.FAIL.getIndex()).build();
		}
		return builder.msg("账户不正确").status(Status.FAIL.getIndex()).build();
	}

}